SpringBoot整合WebSocket(看完即入门)

您所在的位置:网站首页 @param args什么意思 SpringBoot整合WebSocket(看完即入门)

SpringBoot整合WebSocket(看完即入门)

2023-03-15 03:36| 来源: 网络整理| 查看: 265

WebSocket 1、什么是webSocket?2、webSocket可以用来做什么?3、webSocket协议4、服务端WebSocket配置类WebSocket操作类 5、webSocket网页客户端工具通讯测试

1、什么是webSocket?

WebSocket是一种在单个TCP连接上进行全双工通信的协议。WebSocket使得客户端和服务器之间的数据交换变得更加简单,允许服务端主动向客户端推送数据。在WebSocket API中,浏览器和服务器只需要完成一次握手,两者之间就直接可以创建持久性的连接,并进行双向数据传输。

2、webSocket可以用来做什么?

利用双向数据传输的特点可以用来完成很多功能,不需要前端轮询,浪费资源。例如:

1、通告功能 2、聊天功能 (如下是逻辑图) 3、实时更新数据功能 4、弹幕

3、webSocket协议

本协议有两部分:握手和数据传输。 握手是基于http协议的。

GET ws://localhost/chat HTTP/1.1 Host: localhost Upgrade: websocket Connection: Upgrade Sec-WebSocket-Key:dGhlIHNhbXBsZSBub25jZQ== Sec-WebSocket-Protocol: chat,superchat Sec-WebSocket-Version: 13

来自服务器的握手看起来像如下形式:

HTTP/1.1 101 Switching Protocols Upgrade: websocket Connection: Upgrade Sec-WebSocket-Accept:s3pPLMBiTxaQ9kYGzzhZRbK+xOo= Sec-WebSocket-Protocol: chat

4、服务端

maven依赖

org.springframework.boot spring-boot-starter-websocket cn.hutool hutool-core 5.7.22 WebSocket配置类 import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.web.socket.server.standard.ServerEndpointExporter; /** * @author Hao * @date 2023-03-01 16:18 * @description: * @version: */ @Configuration public class WebSocketConfig { /** * 注入ServerEndpointExporter, * 这个bean会自动注册使用了@ServerEndpoint注解声明的Websocket endpoint */ @Bean public ServerEndpointExporter serverEndpointExporter() { return new ServerEndpointExporter(); } } WebSocket操作类

通过该类WebSocket可以进行群推送以及单点推送

import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import org.springframework.stereotype.Component; import cn.hutool.core.util.StrUtil; import javax.websocket.*; import javax.websocket.server.PathParam; import javax.websocket.server.ServerEndpoint; import java.io.IOException; import java.util.concurrent.ConcurrentHashMap; /** * @author Hao * @date 2023-03-01 16:18 * @description: * @version: */ @ServerEndpoint(value = "/websocket/{userId}") @Component public class WebSocket { private final static Logger logger = LogManager.getLogger(WebSocket.class); /** * 静态变量,用来记录当前在线连接数。应该把它设计成线程安全的 */ private static int onlineCount = 0; /** * concurrent包的线程安全Map,用来存放每个客户端对应的MyWebSocket对象 */ private static ConcurrentHashMap webSocketMap = new ConcurrentHashMap(); /** * 与某个客户端的连接会话,需要通过它来给客户端发送数据 */ private Session session; private String userId; /** * 连接建立成功调用的方法 */ @OnOpen public void onOpen(Session session, @PathParam("userId") String userId) { this.session = session; this.userId = userId; //加入map webSocketMap.put(userId, this); addOnlineCount(); //在线数加1 logger.info("用户{}连接成功,当前在线人数为{}", userId, getOnlineCount()); try { sendMessage(String.valueOf(this.session.getQueryString())); } catch (IOException e) { logger.error("IO异常"); } } /** * 连接关闭调用的方法 */ @OnClose public void onClose() { //从map中删除 webSocketMap.remove(userId); subOnlineCount(); //在线数减1 logger.info("用户{}关闭连接!当前在线人数为{}", userId, getOnlineCount()); } /** * 收到客户端消息后调用的方法 * * @param message 客户端发送过来的消息 */ @OnMessage public void onMessage(String message, Session session) { logger.info("来自客户端用户:{} 消息:{}",userId, message); //群发消息 /*for (String item : webSocketMap.keySet()) { try { webSocketMap.get(item).sendMessage(message); } catch (IOException e) { e.printStackTrace(); } }*/ } /** * 发生错误时调用 * * @OnError */ @OnError public void onError(Session session, Throwable error) { logger.error("用户错误:" + this.userId + ",原因:" + error.getMessage()); error.printStackTrace(); } /** * 向客户端发送消息 */ public void sendMessage(String message) throws IOException { this.session.getBasicRemote().sendText(message); //this.session.getAsyncRemote().sendText(message); } /** * 通过userId向客户端发送消息 */ public void sendMessageByUserId(String userId, String message) throws IOException { logger.info("服务端发送消息到{},消息:{}",userId,message); if(StrUtil.isNotBlank(userId)&&webSocketMap.containsKey(userId)){ webSocketMap.get(userId).sendMessage(message); }else{ logger.error("用户{}不在线",userId); } } /** * 群发自定义消息 */ public static void sendInfo(String message) throws IOException { for (String item : webSocketMap.keySet()) { try { webSocketMap.get(item).sendMessage(message); } catch (IOException e) { continue; } } } public static synchronized int getOnlineCount() { return onlineCount; } public static synchronized void addOnlineCount() { WebSocket.onlineCount++; } public static synchronized void subOnlineCount() { WebSocket.onlineCount--; } }

测试controller

import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; import java.io.IOException; /** * @author Hao * @date 2023-03-01 16:18 * @description: * @version: */ @RestController @RequestMapping("/webSocket") public class WebSocketController { @Autowired private WebSocket webSocket; @PostMapping("/sentMessage") public void sentMessage(String userId,String message){ try { webSocket.sendMessageByUserId(userId,message); } catch (IOException e) { e.printStackTrace(); } } } 5、webSocket网页客户端工具 http://websocket.jsonin.com/

复制三个tab

WebSocket地址分别输入后连接

ws://127.0.0.1:8051/websocket/1 ws://127.0.0.1:8051/websocket/2 ws://127.0.0.1:8051/websocket/3

通讯测试

1.往客户端发消息

127.0.0.1:8092/webSocket/sentMessage?userId=1&message=请进入视频会议 127.0.0.1:8092/webSocket/sentMessage?userId=2&message=请进入视频会议 127.0.0.1:8092/webSocket/sentMessage?userId=3&message=请进入视频会议

2.客户端收到消息回复“好的”

最后送所有正在努力的大家一句话:

你不一定逆风翻盘,但一定要向阳而生。 期待下次发布好的文章: 山水相逢,我们江湖见。


【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3